from model.House_info import House_info
# 报错 sqlalchemy.exc.OperationalError:（由于Query调用的自动刷新而引发；如果此刷新过早发生，请考虑使用session.no_autoflush块
# 解决方法
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

import json
from datetime import datetime

from db import db

from utils.query import querys

# 引入数据模型（表）
from model.User import User
from model.History import History

# 省 - 城市
cityList = [
    {'province': '北京', 'city': ['北京']},
    {'province': '天津', 'city': ['天津']},
    {'province': '河北', 'city': ['石家庄', '唐山', '秦皇岛', '邯郸', '邢台', '保定', '张家口', '承德', '沧州', '廊坊', '衡水']},
    {'province': '山西', 'city': ['太原', '大同', '长治', '晋城', '朔州', '晋中', '运城', '忻州', '临汾', '吕梁']},
    {'province': '内蒙古', 'city': ['呼和浩特', '包头', '乌海', '赤峰', '通辽', '鄂尔多斯', '呼伦贝尔', '巴彦淖尔', '乌兰察布', '兴安盟', '锡林郭勒盟', '阿拉善盟']},
    {'province': '辽宁', 'city': ['沈阳', '大连', '鞍山', '抚顺', '本溪', '丹东', '锦州', '营口', '阜新', '辽阳', '盘锦', '朝阳', '葫芦岛']},
    {'province': '吉林', 'city': ['长春', '吉林', '四平', '辽源', '通化', '白山', '松原', '白城', '延边']},
    {'province': '黑龙江', 'city': ['哈尔滨', '齐齐哈尔', '鸡西', '鹤岗', '双鸭山', '大庆', '伊春', '佳木斯', '七台河', '牡丹江', '黑河', '绥化', '大兴安岭地区']},
    {'province': '上海', 'city': ['上海']},
    {'province': '江苏', 'city': ['南京', '无锡', '徐州', '常州', '苏州', '南通', '连云港', '淮安', '盐城', '扬州', '镇江', '秦州', '宿迁']},
    {'province': '浙江', 'city': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衡州', '舟山', '台州', '丽水']},
    {'province': '安徽', 'city': ['石家庄', '合肥', '芜湖', '蚌埠', '淮南', '马鞍山', '淮北', '铜陵', '安庆', '黄山', '滁州', '阜阳', '宿州', '六安', '毫州', '池州', '宣城']},
    {'province': '福建', 'city': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德']},
    {'province': '江西', 'city': ['南昌', '景德镇', '萍乡', '九江', '新余', '鹰潭', '赣州', '吉安', '宜春', '抚州']},
    {'province': '山东', 'city': ['济南', '青岛', '淄博', '枣庄', '东营', '烟台', '潍坊', '济宁', '秦安', '威海', '日照', '莱芜', '临沂', '德州', '聊城', '滨州', '菏泽']},
    {'province': '河南', 'city': ['郑州', '开封', '洛阳', '平顶山', '安阳', '鹤壁', '新乡', '焦作', '济源', '濮阳', '许昌', '漯河', '三门峡', '南阳', '商丘', '信阳', '周口', '驻马店']},
    {'province': '湖北', 'city': ['武汉', '黄石', '十堰', '宜昌', '襄阳', '鄂州', '荆门', '孝感', '荆州', '黄冈', '咸宁', '随州', '恩施', '仙桃', '潜江', '天门', '神农架林区']},
    {'province': '湖南', 'city': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西']},
    {'province': '广东', 'city': ['广州', '韶关', '深圳', '珠海', '汕头', '佛山', '江门', '湛江', '茂名', '肇庆', '惠州', '梅州', '汕尾', '河源', '阳江', '清远', '东莞', '中山', '东沙群岛', '潮州', '揭阳', '云浮']},
    {'province': '广西', 'city': ['南宁', '柳州', '桂林', '梧州', '北海', '防城港', '钦州', '贵港', '玉林', '百色', '贺州', '河池', '来宾', '崇左']},
    {'province': '海南', 'city': ['三亚', '三沙', '五指山', '琼海', '儋州', '文昌', '万宁', '东方', '定安', '屯昌', '澄迈', '临高', '白沙', '昌江', '乐东', '陵水', '保亭', '琼中']},
    {'province': '重庆', 'city': ['重庆']},
    {'province': '四川', 'city': ['成都', '自贡', '攀枝花', '泸州', '德阳', '绵阳', '广元', '遂宁', '内江', '乐山', '南充', '眉山', '宜宾', '广安', '达州', '雅安', '巴中', '资阳', '阿坝', '甘孜', '凉山']},
    {'province': '贵州', 'city': ['贵阳', '六盘水', '遵义', '安顺', '铜仁', '黔西南', '毕节', '黔东南', '黔南']},
    {'province': '云南', 'city': ['昆明', '曲靖', '玉溪', '保山', '昭通', '丽江', '普洱', '临沧', '楚雄', '红河', '文山', '西双版纳', '大理', '德宏', '怒江', '迪庆']},
    {'province': '西藏', 'city': ['拉萨', '昌都', '山海', '日喀则', '那曲', '阿里', '林芝']},
    {'province': '陕西', 'city': ['西安', '铜川', '宝鸡', '咸阳', '渭南', '延安', '汉中', '榆林', '安康', '商洛']},
    {'province': '甘肃', 'city': ['兰州', '嘉峪关', '金昌', '白银', '天水', '武威', '张掖', '平凉', '酒泉', '庆阳', '定西', '陇南', '临夏', '甘南']},
    {'province': '青海', 'city': ['西宁', '海东', '海北', '黄南', '海南', '果洛', '玉树', '海西']},
    {'province': '宁夏', 'city': ['银川', '石嘴山', '吴忠', '固原', '中卫']},
    {'province': '新疆', 'city': ['乌鲁木齐', '克拉玛依', '吐鲁番', '哈密', '昌吉', '博尔塔拉', '巴音郭楞', '阿克苏', '克孜勒苏柯尔克孜', '喀什', '和田', '伊犁', '塔城', '阿勒泰', '石河子', '阿拉尔', '图木舒克', '五家渠']},
    {'province': '台湾', 'city': ['台北', '高雄', '台南', '台中', '金门', '南投', '基隆', '新竹', '嘉义', '新北', '宜兰', '新竹县', '桃园', '苗栗', '彰化县', '嘉义县', '云林县', '屏东县', '台东县', '花莲县', '澎湖县', '连江县']},
    {'province': '香港', 'city': ['香港岛', '新县']},
    {'province': '澳门', 'city': ['澳门', '离岛']},
]

# 获取所有房屋数据 -- 处理json.dumps()数据
def getAllHouse_info(city=''):
    # 获取所有房屋数据
    if city:
        try:
            houseList = House_info.query.filter_by(city=city).all()
        except:
            # 报错解决方法
            engine = create_engine('mysql+pymysql://root:123456@localhost:3306/house_data')
            Session = sessionmaker(bind=engine)
            session = Session()
            # 在查询之前禁用自动刷新
            with session.no_autoflush:
                # 返回获取到的id值所在的房屋信息
                houseList = session.query(House_info).filter_by(city=city).all()
    else:
        houseList = House_info.query.all()
    # 处理数据 -- 将数组进行转化加载
    def map_fn(item):
        # rooms_desc -- 居室
        item.rooms_desc = json.loads(item.rooms_desc)
        # area_range -- 房屋面积范围
        item.area_range = json.loads(item.area_range)
        # tags -- 标签
        item.tags = json.loads(item.tags)
        # totalPrice_range -- 房屋价格区间
        item.totalPrice_range = json.loads(item.totalPrice_range)
        # 返回每行
        return item
    # 将数据存入新的变量中
    houseListMap = list(map(map_fn, houseList))
    # 返回新数组
    return houseListMap

# 获取全部城市数据
def getCitiesList():
    hourseList = list(set([x.city for x in House_info.query.all()]))
    return hourseList

# 获取id值 - 查看详情、删除等
def getHouseInfoById(id):
    try:
        house_info = House_info.query.filter_by(id=id).first()
    except:
        # 报错解决方法
        engine = create_engine('mysql+pymysql://root:123456@localhost:3306/house_data')
        Session = sessionmaker(bind=engine)
        session = Session()
        # 在查询之前禁用自动刷新
        with session.no_autoflush:
            # 返回获取到的id值所在的房屋信息
            house_info = session.query(House_info).filter_by(id=id).first()

    # 对数据进行处理
    # rooms_desc -- 居室
    house_info.rooms_desc = json.loads(house_info.rooms_desc)
    # area_range -- 房屋面积范围
    house_info.area_range = json.loads(house_info.area_range)
    # tags -- 标签
    house_info.tags = json.loads(house_info.tags)
    # totalPrice_range -- 房屋价格区间
    house_info.totalPrice_range = json.loads(house_info.totalPrice_range)

    return house_info

# 预测数据添加
def addHisotry(city,price,username):
    user = User.query.filter_by(user_name=username).first()
    newHistory = History(city=city,price=price,user=user)
    db.session.add(newHistory)
    db.session.commit()

# 获取添加的数据
def addHouseInfo(houseInfo):
    # print(houseInfo)
    # 处理房型数据
    houseInfo['rooms_desc'] = json.dumps(houseInfo['rooms_desc'].split('，'))
    # 处理建面数据
    houseInfo['area_range'] = json.dumps(houseInfo['area_range'].split('-'))
    # 处理标签数据
    houseInfo['tags'] = json.dumps(houseInfo['tags'].split('，'))
    houseInfo['all_ready'] = '1'
    houseInfo['on_time'] = '0000-00-00 00:00:00'
    # 处理总价范围情况
    houseInfo['totalPrice_range'] = json.dumps([0])
    # 售房情况
    houseInfo['sale_status'] = '1'
    # 详情链接
    houseInfo['detail_url'] = '0'
    # 获取当前时间
    now = datetime.now()
    houseInfo['open_date'] = f"{now.year}-{now.month:02d}-{now.day:02d}"
    # print(houseInfo)
    # 写入数据库
    houseInfo_new = House_info(title=houseInfo['title'], city=houseInfo['city'], region=houseInfo['region'],
                               address=houseInfo['address'], rooms_desc=houseInfo['rooms_desc'],
                               area_range=houseInfo['area_range'], price=houseInfo['price'],
                               houseDecoration=houseInfo['houseDecoration'],
                               company=houseInfo['company'], houseType=houseInfo['houseType'], tags=houseInfo['tags'],
                               cover=houseInfo['cover'], all_ready=houseInfo['all_ready'],
                               on_time=houseInfo['on_time'], totalPrice_range=houseInfo['totalPrice_range'],
                               sale_status=houseInfo['sale_status'],
                               detail_url=houseInfo['detail_url'], open_date=houseInfo['open_date']
                               )
    db.session.add(houseInfo_new)
    db.session.commit()

# 修改已存在的房屋数据
def editHouseInfo(house_info, id):
    # 处理房型数据
    house_info['rooms_desc'] = json.dumps(house_info['rooms_desc'].split('，'))
    # 处理建面数据
    house_info['area_range'] = json.dumps(house_info['area_range'].split('-'))
    # 处理标签数据
    house_info['tags'] = json.dumps(house_info['tags'].split('，'))
    # 获取当前id的房屋数据
    house = getHouseInfoById(id)
    print(house.price)
    # 更新数据
    house.title = house_info['title']
    house.city = house_info['city']
    house.region = house_info['region']
    house.address = house_info['address']
    house.rooms_desc = house_info['rooms_desc']
    house.area_range = house_info['area_range']
    house.price = house_info['price']
    house.houseDecoration = house_info['houseDecoration']
    house.company = house_info['company']
    house.houseType = house_info['houseType']
    house.tags = house_info['tags']
    if house_info['cover'] != '0':
        house.cover = house_info['cover']
    print(house.price)
    # 更新数据库
    db.session.commit()

# 删除数据
def delHouseInfoById(id):
    house_info = getHouseInfoById(id)
    db.session.delete(house_info)
    db.session.commit()

# 获取预测表数据 -- history表
def getUserHistoryData(username):
    user = querys('select * from user where user_name = %s', [username], 'select')[0]
    # 获取预测表列表
    historyList = querys('select * from history where user_id = %s', [int(user[0])], 'select')
    # 获取最贵价格
    maxPrice = 0
    # 预测的各城市个数
    cityLenDict = {}
    for data in historyList:
        if maxPrice < float(data[2]):
            maxPrice = float(data[2])
        if cityLenDict.get(data[1], -1) == -1:
            cityLenDict[data[1]] = 1
        else:
            cityLenDict[data[1]] += 1
    # 用户预测的最多城市 -- 按降序排序、取第一个
    sortedCityLen = list(sorted(cityLenDict.items(), key=lambda x: x[1], reverse=True))
    # 各城市占比
    cityPieData = []
    for key, value in cityLenDict.items():
        cityPieData.append({
            'name': key,
            'value': round(value / len(historyList), 2)
        })
    # print(cityPieData)

    return historyList, len(historyList), maxPrice, sortedCityLen[0][0], cityPieData

# test
# print(getHouseInfoById(10))